<

dart:ffi を使用したネイティブ macOS コードへのバインド

Flutter モバイル アプリとデスクトップ アプリでは、ダーツ:ffiネイティブ C API を呼び出すためのライブラリ。FFIを意味する外部関数インターフェイス。同様の機能を表すその他の用語には次のものがあります。ネイティブインターフェース言語のバインディング。

ライブラリまたはプログラムが FFI ライブラリを使用できるようになる前に ネイティブ コードにバインドするには、次のことを確認する必要があります。 ネイティブ コードがロードされ、そのシンボルが Dart に表示されます。 このページはコンパイル、パッケージ化、 Flutter プラグインまたはアプリ内で macOS ネイティブ コードをロードします。

このチュートリアルでは、C/C++ をバンドルする方法を説明します。 Flutter プラグイン内のソースを使用してバインドします。 macOS 上の Dart FFI ライブラリ。 このチュートリアルでは、C 関数を作成します 32ビット加算を実装し、 「native_add」という名前の Dart プラグインを通じてそれを公開します。

動的リンクと静的リンク

ネイティブ ライブラリはアプリにリンクできます。 動的または静的に。静的にリンクされたライブラリ アプリの実行可能イメージに埋め込まれており、 アプリの起動時に読み込まれます。

静的にリンクされたライブラリのシンボルは、 を使用してロードされました793ae93e-a602-4f70-a04c-9​​89205290c66またDynamicLibrary.process

対照的に、動的にリンクされたライブラリは分散されます。 アプリ内の別のファイルまたはフォルダーに、 そしてオンデマンドでロードされます。 macOS では、動的にリンクされた ライブラリはとして配布されます.frameworkフォルダ。

動的にリンクされたライブラリは、 ダーツの使い方DynamicLibrary.open

API ドキュメントは Dart 開発チャネルから入手できます。Dart API リファレンス ドキュメント。

ステップ 1: プラグインを作成する

すでにプラグインをお持ちの場合は、この手順をスキップしてください。

「native_add」というプラグインを作成するには、 以下をせよ:

$ flutter create --platforms=macos --template=plugin native_add
$ cd native_add

ステップ 2: C/C++ ソースを追加する

macOS ビルド システムに次のことを通知する必要があります。 ネイティブコードなのでコードをコンパイルできる そして最終的なアプリケーションに適切にリンクされます。

ソースをmacosフォルダ、 CocoaPods ではソースを含めることができないため、 の上podspecファイル。

FFI ライブラリは C シンボルに対してのみバインドできます。 したがって、C++ では、これらのシンボルをマークする必要がありますextern C。 また、次のことを示す属性も追加する必要があります。 シンボルは Dart から参照されます。 リンカーがシンボルを破棄しないようにするため リンク時の最適化中。

例えば、 という名前の C++ ファイルを作成しますmacos/Classes/native_add.cpp、 次の手順を使用してください。 (テンプレートは このファイルはすでに作成されています)。 プロジェクトのルート ディレクトリ:

cat > macos/Classes/native_add.cpp << EOF
#include <stdint.h>

extern "C" __attribute__((visibility("default"))) __attribute__((used))
int32_t native_add(int32_t x, int32_t y) {
    return x + y;
}
EOF

macOS では、ファイルを静的にリンクするように Xcode に指示する必要があります。

  1. Xcode で開きますRunner.xcworkspace
  2. C/C++/Objective-C/Swift を追加します。 ソース ファイルを Xcode プロジェクトに追加します。

ステップ 3: FFI ライブラリを使用してコードをロードする

この例では、次のコードを追加できますlib/native_add.dart。ただし、その場所は、 Dart バインディング コードは重要ではありません。

まず、DynamicLibraryハンドル ネイティブコード。

import 'dart:ffi'; // For FFI

final DynamicLibrary nativeAddLib = DynamicLibrary.process();

周囲のライブラリへのハンドルを使用すると、 を解決できますnative_addシンボル:

final int Function(int x, int y) nativeAdd = nativeAddLib
    .lookup<NativeFunction<Int32 Function(Int32, Int32)>>('native_add')
    .asFunction();

ようやく、呼び出すことができます。これを実証するには 自動生成された「サンプル」アプリ (example/lib/main.dart):

// Inside of _MyAppState.build:
        body: Center(
          child: Text('1 + 2 == ${nativeAdd(1, 2)}'),
        ),

その他の使用例

iOSとmacOS

動的にリンクされたライブラリは、次のように自動的にロードされます。 アプリ起動時の動的リンカー。彼らの構成員 シンボルは次を使用して解決できますDynamicLibrary.process。 次のコマンドを使用してライブラリへのハンドルを取得することもできますDynamicLibrary.open~の範囲を制限する シンボル解決が行われますが、Apple がどのように解決するかは不明です。 レビュープロセスがこれを処理します。

アプリケーションバイナリに静的にリンクされたシンボル を使用して解決できますDynamicLibrary.executableまたDynamicLibrary.process

プラットフォームライブラリ

プラットフォーム ライブラリにリンクするには、 次の手順を使用してください。

  1. Xcode で開きますRunner.xcworkspace
  2. ターゲット プラットフォームを選択します。
  3. クリック+の中にリンクされたフレームワークとライブラリセクション。
  4. リンクするシステム ライブラリを選択します。

ファーストパーティライブラリ

ファーストパーティのネイティブ ライブラリは、次のいずれかを含めることができます。 ソースとして、または(署名付き)として.frameworkファイル。 おそらく静的にリンクされたものを含めることが可能です アーカイブも可能ですが、テストが必要です。

ソースコード

ソースコードに直接リンクするには、 次の手順を使用してください。

  1. Xcode で開きますRunner.xcworkspace
  2. C/C++/Objective-C/Swift を追加します。 ソース ファイルを Xcode プロジェクトに追加します。
  3. 次のプレフィックスを追加します エクスポートされたシンボル宣言 Dart からは見えます:

    C/C++/目的 C

    extern "C" /* <= C++ only */ __attribute__((visibility("default"))) __attribute__((used))
    

    迅速

    @_cdecl("myFunctionName")
    

コンパイルされた (動的) ライブラリ

コンパイルされた動的ライブラリにリンクするには、 次の手順を使用してください。

  1. 正しく署名されていれば、Frameworkファイルは存在しますが、 開けるRunner.xcworkspace
  2. フレームワーク ファイルを埋め込みバイナリセクション。
  3. また、リンクされたフレームワークとライブラリXcode のターゲットのセクション。

コンパイル済み (動的) ライブラリ (macOS)

クローズドソースライブラリを追加するにはFlutter macOS デスクトップアプリ、 次の手順を使用してください。

  1. Flutter デスクトップの手順に従って作成します。 Flutter デスクトップ アプリ。
  2. を開きますyourapp/macos/Runner.xcworkspaceXcodeで。
    1. プリコンパイルされたライブラリをドラッグします (libyourlibrary.dylib) の中へRunner/Frameworks
    2. クリックRunnerそして、に行きますBuild Phasesタブ。
      1. 引っ張るlibyourlibrary.dylibCopy Bundle Resourcesリスト。
      2. Embed Libraries、 チェックCode Sign on Copy
      3. Link Binary With Libraries、 ステータスをに設定Optional。 (動的リンクを使用しています。 静的にリンクする必要はありません。)
    3. クリックRunnerそして、に行きますGeneralタブ。
      1. 引っ張るlibyourlibrary.dylibフレームワーク、 ライブラリと埋め込みコンテンツリスト。
      2. 選択する埋め込みと署名
    4. クリックランナーそして、に行きますビルド設定タブ。
      1. の中に検索パスセクションで設定するライブラリ検索パスパスを含めるには どこlibyourlibrary.dylib位置しています。
  3. 編集lib/main.dart
    1. 使用DynamicLibrary.open('libyourlibrary.dylib')シンボルに動的にリンクします。
    2. ウィジェット内のどこかでネイティブ関数を呼び出します。
  4. 走るflutter runネイティブ関数が呼び出されることを確認します。
  5. 走るflutter build macos自己完結型リリースを構築するには アプリのバージョン。